/* eslint-disable no-undef */
import statchart from "./statchart.js";
import * as utils from "./utils.js";
export let geodatas = [];
// export let defaulgradient = ["#fafa6e","#2A4858"];
export let defaulgradient = ["#FFEBEE","#B71C1C"];
export let defaultminsize = 5;
export let defaultmaxsize = 40;
// import "../lib/terraformer-1.0.12.min.js"
// import "../lib/terraformer-wkt-parser.js"
export async function grid({ theme, map, layer, layerid }) {
  let source = addSource(map, layerid);
  let area = layer.area ? layer.area : globalarea;
  let squareGrid = await utils.nodeapi('squaregrid',{
    level:utils.getlevel(area),
    gridsize:theme.gridsize,
    area
  });
  geodatas[layerid] = squareGrid;
  source.setData(squareGrid);
  if (!map.getLayer(layerid)) {
    map.addLayer({
      id: layerid,
      type: "fill",
      source: source.id, // reference the data source
      layout: {},
    });
  }

  grid_upd({ map, layerid, theme });

  /** 前端计算grid */
  // let outgeo, bbox;
  // outgeo = utils.geodata(utils.getlevel(layer.area),theme.field,utils.getfilter(layer.area));
  // bbox = turf.bbox(outgeo);
  // // let newfts = multi2polygon(layer);
  // // let combine = turf.dissolve( turf.featureCollection(newfts));
  // var options = { mask: outgeo };
  // console.log(new Date().toTimeString());
  // var squareGrid = turf.squareGrid(bbox, theme.gridsize ?? 10, options);
  // console.log(new Date().toTimeString());

  /** 递归计算 */
  // let ftidx = 0;
  // let end = false;
  // function getsquare() {
  //   let ft = squareGrid.features[ftidx];
  //   utils
  //     .nodeapi("spatialSummary", {
  //       level: "cun",
  //       fields: theme.field,
  //       geo: Terraformer.WKT.convert(ft.geometry),
  //     })
  //     .then((res) => {
  //       ft.properties[theme.field] = res[theme.field] * 1;
  //       source.setData(squareGrid);
  //       ftidx++;
  //       if (ftidx >= squareGrid.features.length) {
  //         if (!end) {
  //           let vals = squareGrid.features.map(
  //             (f) => f.properties[theme.field] * 1
  //           );
  //           theme.minmax = { min: d3.min(vals), max: d3.max(vals) };
  //           let colorrender = [
  //             "interpolate",
  //             ["linear"],
  //             ["get", theme.field],
  //             theme.minmax.min,
  //             defaulgradient[0],
  //             theme.minmax.max,
  //             defaulgradient[1],
  //           ];
  //           console.log(colorrender, squareGrid);
  //           map.setPaintProperty(layerid, "fill-color", colorrender);
  //         }
  //         end = true;
  //         return;
  //       } else getsquare(ftidx);
  //     });
  // }
  // for (let i = 0; i < (theme.threadcount || 20); i++) {
  //   getsquare();
  // }

  /** 后端计算grid */
  // let squareGrid = await utils.nodeapi('grid',{
  //   level:'cun',
  //   field:theme.field,
  //   outgeo:JSON.stringify(outgeo),
  //   gridsize:theme.gridsize??10
  // },'post')
  // console.log(squareGrid)

}

export function grid_upd({ map, layerid, theme }) {
  if (map.getPaintProperty(layerid, 'fill-color')) {
    let colorrender = [
      "interpolate",
      ["linear"],
      ["get", theme.field],
      theme.minmax.min,
      defaulgradient[0],
      theme.minmax.max,
      defaulgradient[1],
    ];
    // console.log(colorrender, squareGrid);
    map.setPaintProperty(layerid, "fill-color", colorrender);
  } else {
    map.setPaintProperty(layerid, "fill-color", [
      "case",
      ["has", theme.field],
      "red",
      theme.color || "white",
    ]);
  }
  map.setPaintProperty(layerid, "fill-opacity", theme.opacity ?? 0.5);
  map.setPaintProperty(
    layerid,
    "fill-outline-color",
    theme.outlinecolor ?? "black"
  );
}
// eslint-disable-next-line no-unused-vars
function multi2polygon(layer) {
  let newfts = [];
  geodatas[layer.level].features.forEach((ft) => {
    ft.geometry.coordinates.forEach(function (coords) {
      let feat = turf.polygon(coords);
      newfts.push(feat);
    });
  });
  return newfts;
}

export async function sde({ theme, map, layer, layerid }) {
  let ell = await utils.nodeapi("sde", {
    level: layer.level,
    field: theme.field,
    filter: utils.getfilter(layer.area),
    devmulti: theme.devmulti,
  });
  let sdEllipse = turf.featureCollection([ell]);
  let source = addSource(map, layerid);
  source.setData(sdEllipse);
  if (!map.getLayer(layerid)) {
    map.addLayer({
      id: layerid,
      type: "fill",
      source: source.id, // reference the data source
      layout: {},
    });
  }
  map.setPaintProperty(layerid, "fill-color", theme.color ?? "red");
  map.setPaintProperty(layerid, "fill-opacity", theme.opacity ?? 0.5);
}

function addSource(map, layerid) {
  if (!map.getSource(`src-${layerid}`)) {
    map.addSource(`src-${layerid}`, {
      type: "geojson",
      data: turf.featureCollection([]),
    });
  }
  let source = map.getSource(`src-${layerid}`);
  return source;
}
export async function iso({ theme, map, layer, app, layerid }) {
  if (theme.field) {
    app.loading = true;
    console.log(new Date().toTimeString());
    //计算密度
    let bands = await $.ajax({
      timeout: 1000000,
      url: `http://${ipapi}/iso`,
      data: {
        level: layer.level,
        filter: utils.getfilter(layer.area),
        field: theme.field,
        density: theme.density,
        // calc: "kriging",
      },
      dataType: "json",
    });
    // console.log(new Date().toTimeString(),bands);
    app.loading = false;
    let source = addSource(map, layerid);
    bands && source.setData(turf.featureCollection(bands));
    if (!map.getLayer(layerid)) {
      map.addLayer({
        id: layerid,
        type: "fill",
        source: source.id,
        layout: {},
        paint: {
          "fill-color": ["get", "fill"],
          "fill-opacity": [
            "case",
            ["boolean", ["feature-state", "hover"], false],
            0.8,
            0.5,
          ],
          "fill-outline-color": [
            "case",
            ["boolean", ["feature-state", "hover"], false],
            "#000",
            "#fff",
          ],
        },
      });
    }
  }
}

export async function getminmax(theme, layer) {
  let minmax = await $.getJSON(
    encodeURI(
      `http://${ipapi}/getminmax?field=${
        theme.density ? theme.field + "/area" : theme.field
      }&level=${layer.level}&filter=${utils.getfilter(layer.area)}`
    )
  );
  return minmax;
}

export async function heat({ theme, map, layer, layerid }) {
  if (theme.field) {
    theme.minmax = await getminmax(theme, layer);
    if (!map.getLayer(layerid)) {
      map.addLayer({
        id: layerid,
        type: "heatmap",
        source: `src-${layer.level}-pt`,
      });
    }
    await heat_upd({ map, layerid, theme, layer });
  }
}

export async function heat_upd({ map, layerid, theme, layer }) {
  if (theme.field) {
    if (!theme.minmax) theme.minmax = await getminmax(theme, layer);
    map.setPaintProperty(layerid, "heatmap-weight", [
      "interpolate",
      ["linear"],
      ["get", theme.field],
      theme.minmax.min,
      0,
      theme.minmax.max,
      theme.weight ?? 1,
    ]);
    // let render = heatcolorrender(theme,geodatas[layerid],theme.minmax);
    // console.log(render)
    // render = [ "interpolate", ["linear"], ["heatmap-density"], 0, "rgba(33,102,172,0)", 0.2, "rgb(103,169,207)", 0.4, "rgb(209,229,240)", 0.6, "rgb(253,219,199)", 0.8, "rgb(239,138,98)", 1, "rgb(178,24,43)", ]
    // console.log(render)
    // map.setPaintProperty(layerid, "heatmap-color",render.colorrender );
    map.setPaintProperty(layerid, "heatmap-radius", theme.radius ?? 10);
    map.setPaintProperty(layerid, "heatmap-intensity", theme.intensity ?? 0.5);
  }
}

export async function symbol({ geodata, theme, map, layer, app }) {
  // if (theme.field) {
  //   let minmax = await $.getJSON(
  //     encodeURI(
  //       `http://${ipapi}/getminmax?field=${
  //         theme.density ? theme.field + "/area" : theme.field
  //       }&level=${level}&filter=${filter}`
  //     )
  //   );
  //   // let ret = await fillcolorrender(theme, geodata,  minmax, map,level);
  //   // let colorrender = ret.colorrender;

  //   map.getLayer(`symbol-${level}`) && map.removeLayer(`symbol-${level}`);
  //   map.addLayer({
  //     id: `symbol-${level}`,
  //     type: "symbol",
  //     source: `src-${level}-pt`,
  //     layout: {
  //       "icon-allow-overlap":true,
  //       "icon-image": theme.image,
  //       "icon-size": [
  //         "interpolate",
  //         ["linear"],
  //         ["get", theme.field],
  //         minmax.min,
  //         theme.minsize ?? 1,
  //         minmax.max,
  //         theme.maxsize ?? 1,
  //       ],
  //     },
  //   });
  // }
  let nodeminmax, scale;
  if (theme.field) {
    nodeminmax = await $.getJSON(
      encodeURI(
        `http://${ipapi}/getminmax?field=${theme.field}&level=${
          layer.level
        }&filter=${utils.getfilter(layer.area)}`
      )
    );
    scale = d3
      .scaleLinear()
      .range([theme.minsize ?? 20, theme.maxsize ?? 80])
      .domain([nodeminmax.min, nodeminmax.max]);
  }
  geodata.features.forEach((ft) => {
    const el = document.createElement("img");
    el.src = "../img/icon/" + theme.image + ".png";
    // el.className = "el-icon-platform-eleme";
    el.className = "marker";
    let size = scale ? scale(ft.properties[theme.field]) : 50;
    el.style.width = `${size}px`;
    el.style.height = `${size}px`;
    let mk = new mapboxgl.Marker(el)
      .setLngLat(ft.geometry.coordinates)
      .addTo(map);
    app.markers.push(mk);
  });
}

export async function chart({ geodata, theme, map, layer, app }) {
  let nodeminmax, scale;
  if (theme.field) {
    nodeminmax = await getminmax(theme, layer);
    scale = d3
      .scaleLinear()
      .range([theme.minsize ?? 50, theme.maxsize ?? 100])
      .domain([nodeminmax.min, nodeminmax.max]);
  }
  geodata.features.forEach((ft) => {
    const el = document.createElement("div");
    el.className = "marker";
    let size = scale ? scale(ft.properties[theme.field]) : 50;
    el.style.width = `${size}px`;
    el.style.height = `${size}px`;
    // el.style.backgroundColor='red'
    el.id = "chart" + ft.properties.code;

    let chartdata = [];
    theme.fields.forEach((f) => {
      chartdata.push({
        value: ft.properties[f],
        name: f,
      });
    });
    let option = {
      title: {
        // text: layer.chart.title ?? "",
        left: "center",
      },
      tooltip: {
        trigger: "item",
      },
      legend: {
        show: false,
        orient: "vertical",
        left: "left",
      },
      series: [
        {
          name: "",
          type: "pie",
          radius: "50%",
          data: chartdata,
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
        },
      ],
    };
    // console.log(ft.geometry)
    let mk = new mapboxgl.Marker(el)
      .setLngLat(ft.geometry.coordinates)
      .addTo(map);
    app.markers.push(mk);
    var chart = echarts.init(el);
    chart.setOption(option);
    chart.resize();
  });
}

export async function outline({ map, theme, layer, layerid }) {
  if (!map.getLayer(layerid))
    map.addLayer({
      id: layerid,
      type: "line",
      source: `src-${layer.level}`,
    });
  await outline_upd({ map, layerid, theme });
}

export function outline_upd({ map, layerid, theme }) {
  map.setPaintProperty(layerid, "line-width", theme.width ?? 2);
  map.setPaintProperty(layerid, "line-color", theme.color ?? "red");
  map.setPaintProperty(layerid, "line-blur", theme.blur ?? 0);
}

export async function label({ theme, map, layer, layerid }) {
  if (!map.getLayer(layerid))
    map.addLayer({
      id: layerid,
      type: "symbol",
      source: `src-${layer.level}-pt`,
      layout: {
        "text-field": "{codename}",
        // "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
        "text-offset": [0, -1.5],
      },
    });
  await label_upd({ map, layerid, theme });
}

export function label_upd({ map, layerid, theme }) {
  map.setPaintProperty(layerid, "text-halo-width", theme.halowidth ?? 1);
  map.setPaintProperty(layerid, "text-halo-color", theme.halocolor ?? "white");
  map.setPaintProperty(layerid, "text-color", theme.color ?? "black");
  map.setLayoutProperty(layerid, "text-size", theme.size ?? 12);
  map.setLayoutProperty(layerid, "text-allow-overlap", theme.overlap ?? false);
}

export async function flow({ theme, geodata, map, layer, layerid }) {
  let url_geo = encodeURI(
    `http://${ipapi}/flow?direction=${theme.direction}&level=${
      layer.level
    }&areacode=${theme.areacode}${theme.pure ? "&pure=1" : ""}`
  );
  let geoflow = await $.getJSON(url_geo);
  geoflow = geoflow.geojson;
  let flowfield = theme.pure ? "cnt0" : "cnt";
  let min = ecStat.statistics.min(
    geoflow.features.map((f) => f.properties[flowfield])
  );
  let max = ecStat.statistics.max(
    geoflow.features.map((f) => f.properties[flowfield])
  );
  theme.minmax = { min, max };
  theme.flowfield = flowfield;

  if (theme.fill) {
    //用流动数据地图涂色,净流动用cnt0字段，流入流出用cnt字段
    geodata.features.forEach((ft) => {
      let f = geoflow.features.find(
        (f) =>
          f.properties[
            theme.direction == "in" ? "d8_register_location_code" : "ad_code"
          ] == ft.properties.code
      );
      if (f) {
        ft.properties[flowfield] = f.properties[flowfield];
      }
    });
    map.getSource(`src-${layer.level}`).setData(geodata);
    if (!map.getLayer(layerid + "-fill"))
      map.addLayer({
        id: layerid + "-fill",
        type: "fill",
        source: `src-${layer.level}`,
      });
    console.log(layerid + "-fill");
  }

  //绘制流线图层
  if (!map.getSource(`src-${layerid}`)) {
    map.addSource(`src-${layerid}`, {
      type: "geojson",
      data: turf.featureCollection([]),
      generateId: true,
      lineMetrics: true,
    });
  }
  let source = map.getSource(`src-${layerid}`);
  source.setData(geoflow);

  if (!map.getLayer(layerid))
    map.addLayer({
      id: layerid,
      type: "line",
      source: `src-${layerid}`,
      layout: {
        "line-cap": "square",
      },
    });

  await flow_upd({ map, layerid, theme });

  //绘制箭头
  map.getLayer(`arrow-${layer.level}`) && map.removeLayer(`arrow-${layerid}`);
  map.addLayer({
    id: `arrow-${layerid}`,
    type: "symbol",
    source: `src-${layerid}`,
    layout: {
      "symbol-placement": "line",
      "symbol-spacing": 50,
      "icon-image": "arrowIcon",
      "icon-size": 0.5,
    },
  });

  //绘制关系chart
  if (theme.pure && theme.field) {
    let nodeminmax = await $.getJSON(
      encodeURI(
        `http://${ipapi}/getminmax?field=${theme.field}&level=${layer.level}&filter=${layer.filter}`
      )
    );

    var scale = d3
      .scaleLinear()
      .range([1, 20])
      .domain([nodeminmax.min, nodeminmax.max]);
    let graph = {
      nodes: [],
      links: [],
    };
    geodata.features.forEach((ft) => {
      graph.nodes.push({
        id: ft.properties.code,
        name: ft.properties.code,
        value: ft.properties[theme.field],
        symbolSize: scale(ft.properties[theme.field]),
      });
    });
    graph.categories = graph.nodes;

    geoflow.features.forEach((ft) => {
      graph.links.push({
        source: ft.properties.d8_register_location_code,
        target: ft.properties.ad_code,
        sourceWeight: 0,
        targetWeight: ft.properties.cnt0,
      });
    });
    statchart.antvchord("chart3", graph);
    // statchart.chord("chart3", graph);
  } else {
    createchart(geodata, theme, flowfield);
  }
}

export function flow_upd({ map, layerid, theme }) {
  console.log(layerid);
  if (theme.fill) {
    let colorrender = fillcolorrender(theme, geodatas[layerid], theme.minmax);
    colorrender = [
      "match",
      ["get", "code"],
      theme.areacode,
      theme.colorcenter ?? "red",
      colorrender.colorrender,
    ];
    console.log(colorrender);
    map.setPaintProperty(layerid + "-fill", "fill-color", colorrender);
    map.setPaintProperty(
      layerid + "-fill",
      "fill-opacity",
      theme?.opacity ?? 1
    );
  }
  let widthrender = [
    "interpolate",
    ["linear"],
    ["get", theme.flowfield],
    theme.minmax.min,
    theme.minsize ?? 0.5,
    theme.minmax.max,
    theme.maxsize ?? 10,
  ];

  map.setPaintProperty(layerid, "line-width", widthrender);
  map.setPaintProperty(layerid, "line-gradient", [
    "interpolate",
    ["linear"],
    ["line-progress"],
    0,
    "blue",
    1,
    "red",
  ]);
}
export async function fill({ theme, layer, geodata, map, app, layerid }) {
  if (theme.field) {
    theme.minmax = await getminmax(theme, layer);
    //密度渲染
    if (theme.density) {
      geodata.features.forEach((ft) => {
        ft.properties.density = ft.properties[theme.field] / ft.properties.area;
      });
      map.getSource(`src-${layer.level}`).setData(geodata);
    }
    // echarts
    createchart(geodata, theme, theme.field);
  } else {
    $("#legend").hide();
  }
  rendermap(map, theme, layer.level, layerid);
  await fill_upd({ map, layerid, theme, app, layer });
}

export async function fill_upd({ map, layerid, theme, app, layer }) {
  let colorrender;
  if (theme.field) {
    if (!theme.minmax) theme.minmax = await getminmax(theme, layer);
    let ret = fillcolorrender(theme, geodatas[layer.level], theme.minmax);
    colorrender = ret.colorrender;
    renderlegend(app, ret.colors, ret.vals, theme, layerid);
    map.setPaintProperty(layerid, "fill-color", colorrender);

    let opacity = theme.opacitygradient
      ? [
          "interpolate",
          ["linear"],
          ["get", theme.density ? "density" : theme.field],
          0,
          0,
          theme.minmax.max,
          1,
        ]
      : theme.opacity;
    map.setPaintProperty(layerid, "fill-opacity", opacity ?? 1);
  } else {
    colorrender = utils.randomcolorrender(geodatas[layer.level]);
    map.setPaintProperty(layerid, "fill-color", colorrender);
    map.setPaintProperty(layerid, "fill-opacity", theme.opacity ?? 1);
  }
}

function createchart(geodata, theme, field) {
  let girth = geodata.features.map((ft) =>
    theme.density
      ? [ft.properties.density, ft.properties.codename]
      : [ft.properties[field], ft.properties.codename]
  );
  girth = girth.filter((g) => g[0]);
  statchart.histogram("chart1", girth);
  statchart.boxplot("chart2", girth);
  if (theme.closechart != "chart3") {
    statchart.bar("chart3", girth);
  }
}

export async function scatter({ theme, layer, geodata, map, app, layerid }) {
  if (theme.field) {
    theme.minmax = await getminmax(theme, layer);
    //密度渲染
    if (theme.density) {
      geodata.features.forEach((ft) => {
        ft.properties.density = ft.properties[theme.field] / ft.properties.area;
      });
      map.getSource(`src-${layer.level}-pt`).setData(geodata);
    }

    if (!map.getLayer(layerid)) {
      map.addLayer({
        id: layerid,
        type: "circle",
        source: `src-${layer.level}-pt`,
        paint: {},
      });
    }
    await scatter_upd({ map, layerid, theme, app, layer });
  }
}

export async function scatter_upd({ map, layerid, theme, app, layer }) {
  if (theme.field) {
    if (!theme.minmax) theme.minmax = await getminmax(theme, layer);
    let ret = fillcolorrender(theme, geodatas[layer.level], theme.minmax);
    let colorrender = ret.colorrender;
    console.log(colorrender);
    let circleradius = [
      "interpolate",
      ["linear"],
      ["get", theme.field],
      theme.minmax.min,
      theme.minsize ?? defaultminsize,
      theme.minmax.max,
      theme.maxsize ?? defaultmaxsize,
    ];
    map.setPaintProperty(layerid, "circle-radius", circleradius);
    map.setPaintProperty(layerid, "circle-color", colorrender);
    renderlegend(app, ret.colors, ret.vals, theme, layerid);
  }
}

function rendermap(map, theme, level, layerid) {
  if (!map.getLayer(layerid))
    map.addLayer({
      id: layerid,
      type: "fill",
      source: `src-${level}`,
    });
  if (theme.highlight) {
    const popup = new mapboxgl.Popup({
      closeButton: false,
    });

    map.getLayer(`highlight-${level}`) && map.removeLayer(`highlight-${level}`);
    map.addLayer({
      id: `highlight-${level}`,
      type: "fill",
      source: `src-${level}`,
      paint: {
        "fill-outline-color": "#484896",
        "fill-color": "#6e599f",
        "fill-opacity": 0.75,
      },
      filter: ["==", ["id"], ""],
    });

    map.on("mousemove", layerid, (e) => {
      // Change the cursor style as a UI indicator.
      map.getCanvas().style.cursor = e.features.length ? "pointer" : "";
      let html;
      if (theme.field) {
        html = `<b>${e.features[0].properties.codename}</b><br>${
          e.features[0].properties.code
        }<br>人口数：${
          e.features[0].properties[theme.field]
        }<br>面积：${e.features[0].properties.area.toFixed(
          2
        )}平方公里<br>人口密度：${(
          e.features[0].properties[theme.field] / e.features[0].properties.area
        ).toFixed(2)}人/km`;
      } else {
        html = `<b>${e.features[0].properties.codename}</b><br>${
          e.features[0].properties.code
        }<br>面积：${e.features[0].properties.area.toFixed(2)}平方公里`;
      }
      popup.setLngLat(e.lngLat).setHTML(html).addTo(map);

      map.setFilter(`highlight-${level}`, ["==", ["id"], e.features[0].id]);
    });

    map.on("mouseleave", layerid, () => {
      map.getCanvas().style.cursor = "";
      popup.remove();
      map.setFilter(`highlight-${level}`, ["==", ["id"], ""]);
    });
  }
}

// eslint-disable-next-line no-unused-vars
function heatcolorrender(theme, geodata) {
  let min = 0; //minmax.min;
  let max = 1; //minmax.max;
  let field = theme.field;
  let colorgradient =
    theme.colorgradient?.length >= 2 ? theme.colorgradient : defaulgradient;
  let colorlevels = theme.palette?.length ?? theme.colorlevels ?? 5;
  let colors =
    theme.palette?.length > 0
      ? theme.palette
      : chroma.scale(colorgradient).mode("lch").colors(colorlevels);

  let vals;
  if (theme.quantile) {
    vals = utils.quantileValue(
      geodata.features.map((ft) => ft.properties[field]),
      colorlevels - 2
    );
  } else {
    vals = utils.gradientValue(min, max, colorlevels - 2);
  }
  let colorrender = ["interpolate", ["linear"], ["heatmap-density"]];
  for (let idx = 0; idx < colorlevels; idx++) {
    if (idx == 0) {
      colorrender.push(min);
    } else if (idx == colorlevels - 1) {
      colorrender.push(max);
    } else colorrender.push(vals[idx - 1]);
    if (idx == 0) {
      colorrender.push(chroma(colors[idx]).alpha(0).css());
    } else {
      colorrender.push(colors[idx]);
    }
  }
  vals.push(max);
  return {
    colors,
    colorrender,
    vals,
  };
}

function fillcolorrender(theme, geodata, minmax) {
  let min = minmax.min;
  let max = minmax.max;
  let field = theme.type == "flow" ? theme.flowfield : theme.field;
  let colorgradient =
    theme.colorgradient?.length >= 2 ? theme.colorgradient : defaulgradient;
  let colorlevels = theme.palette?.length || theme.colorlevels || 5;
  let colors =
    theme.palette?.length > 0
      ? theme.palette
      : chroma.scale(colorgradient).mode("lch").colors(colorlevels);

  let vals;
  if (theme.quantile) {
    vals = utils.quantileValue(
      geodata.features.map((ft) =>
        theme.density ? ft.properties.density : ft.properties[field]
      ),
      colorlevels - 1
    );
  } else {
    vals = utils.gradientValue(min, max, colorlevels - 1);
  }
  let colorrender = ["step", ["get", theme.density ? "density" : field]];
  for (let idx = 0; idx < colorlevels; idx++) {
    colorrender.push(colors[idx]);
    if (idx != colorlevels - 1) colorrender.push(vals[idx]);
  }
  vals.push(max);
  return {
    colors,
    colorrender,
    vals,
  };
  // colorrender = [
  //   "interpolate",
  //   ["linear"],
  //   ["get", theme.field],
  //   min,
  //   colorgradient[0],
  //   max,
  //   colorgradient[1],
  // ];
}

function renderlegend(app, colors, vals, theme, layerid) {
  if (theme.field && theme.legend.show) {
    $("#legend").show();
    let scale = d3
      .scaleLinear()
      .range([theme.minsize ?? defaultminsize, theme.maxsize ?? defaultmaxsize])
      .domain([d3.min(vals), d3.max(vals)]);

    theme.legend.items = colors.map((c, idx) => {
      return {
        val: Math.round(
          vals[idx] / (theme.legend?.calcunit ?? 1),
          0
        ).toLocaleString(),
        color: c,
        size: scale(vals[idx]),
      };
    });
    theme.legend.layerid = layerid;
    theme.legend.type = theme.type;
    let lidx = app.legends.findIndex((l) => l.layerid == layerid);
    if (lidx >= 0) {
      app.legends.splice(lidx, 1);
    }
    app.legends.push(theme.legend);
    // console.log(app.legends)
    // app.$forceUpdate();
  }
}
